// 配置加载器类型
import {SimpleAttrs, SimpleRate, SimpleRewards} from "db://assets/proto/shared/v1/biz";
import {
    BuildingConfigs, BuildingUpgradeConfigs,
    ExtraAttrsConfigs,
    FishLevelConfigs, FishLooksConfigs,
    LingGenConfigs, MixingFormulaConfigs, MixPipeConfigs,
    PeculiarityConfigs,
    PeculiaritySkillConfigs, PersonalityConfigs, PlayerLevelConfigs,
    PropsConfigs,
    SkillConfigs,
    TalentConfigs, ZoneConfigs
} from "db://assets/proto/shared/v1/configs";
import Long from "long";
import {cmm} from "db://assets/script/utils/cmm";
import {CSVReader} from "db://assets/script/pkg/csv-reader";
import {_decorator, Component} from "cc";

const {ccclass, property} = _decorator;

export interface GlobalConfigHelper<T> {
    name: string;
    loader: (origin: Record<string, string>[]) => Map<string, T>;
}

export interface KVHelper {
    k: string;
    v: string;
}

@ccclass('GlobalConfigsLoader')
export class GlobalConfigsLoader extends Component {
    static instance: GlobalConfigsLoader = null!

    originConfigs: Map<string, Map<string, any>> = new Map<string, Map<string, any>>();
    configHelpers: GlobalConfigHelper<any>[] = [
        {
            name: "fish_level_configs",
            loader: (origin: Record<string, string>[]) => {
                const rst = new Map<string, FishLevelConfigs>();
                for (const oo of origin) {
                    try {
                        const level = parseInt(oo["level"], 10);
                        const exp = parseInt(oo["exp"], 10);
                        const point = parseInt(oo["point"], 10);

                        if (isNaN(level) || isNaN(exp) || isNaN(point)) {
                            console.warn(`fish_level_configs 数据格式错误:`, oo);
                            continue;
                        }
                        rst.set(oo["level"], FishLevelConfigs.create({
                            level,
                            name: oo["name"] || "",
                            icon: oo["icon"] || "",
                            exp: Long.fromNumber(exp),
                            point: Long.fromNumber(point),
                            attrs: this.simpleAttrsFromRaw(oo["attrs"] || "")
                        }));
                    } catch (error) {
                        console.error(`解析fish_level_configs行数据失败:`, oo, error);
                    }
                }
                return rst;
            }
        },
        {
            name: "extra_attrs_configs",
            loader: (origin: Record<string, string>[]) => {
                const rst = new Map<string, ExtraAttrsConfigs>();

                for (const oo of origin) {
                    try {
                        const propId = Long.fromString(oo["prop_id"]);
                        const config: ExtraAttrsConfigs = {
                            propId: propId,
                            attrs: this.simpleAttrsFromRaw(oo["attrs"] || "")
                        };
                        rst.set(oo["prop_id"], config);
                    } catch (error) {
                        console.error(`解析extra_attrs_configs行数据失败:`, oo, error);
                    }
                }

                return rst;
            }
        },
        {
            name: "talent_configs",
            loader: (origin: Record<string, string>[]) => {
                const rst = new Map<string, TalentConfigs>();

                for (const oo of origin) {
                    try {
                        const config: TalentConfigs = {
                            talentId: Long.fromString(oo["talent_id"]),
                            name: oo["name"] || "",
                            peculiarityOutputRate: this.simpleRateFromRaw(oo["peculiarity_output_rate"] || ""),
                            growthPointUp: Long.fromString(oo["growth_point_up"]),
                            color: oo["color"],
                        };
                        rst.set(oo["talent_id"], config);
                    } catch (error) {
                        console.error(`解析talent_configs行数据失败:`, oo, error);
                    }
                }
                return rst;
            }
        },
        {
            name: "personality_configs",
            loader: (origin: Record<string, string>[]) => {
                const rst = new Map<string, PersonalityConfigs>();
                for (const oo of origin) {
                    try {
                        rst.set(oo["id"], PersonalityConfigs.create(
                            {
                                id: Long.fromString(oo["id"]),
                                name: oo["name"] || "",
                            }
                        ));
                    } catch (error) {
                        console.error(`解析personality_configs行数据失败:`, oo, error);
                    }
                }
                return rst;
            }
        },
        {
            name: "fish_looks_configs",
            loader: (origin: Record<string, string>[]) => {
                const rst = new Map<string, FishLooksConfigs>();
                for (const oo of origin) {
                    try {
                        rst.set(oo["style_id"], FishLooksConfigs.create(
                            {
                                styleId: Long.fromString(oo['style_id']),
                                styleType: oo['style_type'],
                                name: oo["name"] || "",
                            }
                        ));
                    } catch (error) {
                        console.error(`解析fish_looks_configs行数据失败:`, oo, error);
                    }
                }
                return rst;
            }
        },
        {
            name: "skills_configs",
            loader: (origin: Record<string, string>[]) => {
                const rst = new Map<string, SkillConfigs>();

                for (const oo of origin) {
                    try {
                        const skillId = Long.fromString(oo["skill_id"]);
                        const skillType = parseInt(oo["skill_type"], 10);
                        const config: SkillConfigs = {
                            skillId,
                            skillType,
                            name: oo["name"] || "",
                            desc: oo["desc"] || "",
                            factors: this.simpleRateFromRaw(oo["factors"] || "")
                        };

                        rst.set(oo["skill_id"], config);
                    } catch (error) {
                        console.error(`解析skills_configs行数据失败:`, oo, error);
                    }
                }
                return rst;
            }
        },
        {
            name: "ling_gen_configs",
            loader: (origin: Record<string, string>[]) => {
                const rst = new Map<string, LingGenConfigs>();

                for (const oo of origin) {
                    try {
                        const lingGenId = Long.fromString(oo["ling_gen_id"]);
                        const skillId = Long.fromString(oo["skill_id"]);
                        const config: LingGenConfigs = {
                            lingGenId,
                            name: oo["name"] || "",
                            desc: oo["desc"] || "",
                            skillId
                        };

                        rst.set(oo["ling_gen_id"], config);
                    } catch (error) {
                        console.error(`解析ling_gen_configs行数据失败:`, oo, error);
                    }
                }

                return rst;
            }
        },
        {
            name: "peculiarity_configs",
            loader: (origin: Record<string, string>[]) => {
                const rst = new Map<string, PeculiarityConfigs>();

                for (const oo of origin) {
                    try {
                        const peculiarityId = Long.fromString(oo["peculiarity_id"]);
                        const quality = parseInt(oo["quality"], 10);
                        const requiredTalent = parseInt(oo["required_talent"], 10);
                        const config: PeculiarityConfigs = {
                            peculiarityId,
                            quality,
                            name: oo["name"] || "",
                            desc: oo["desc"] || "",
                            requiredTalent
                        };

                        rst.set(oo["peculiarity_id"], config);
                    } catch (error) {
                        console.error(`解析peculiarity_configs行数据失败:`, oo, error);
                    }
                }

                return rst;
            }
        },
        {
            name: "peculiarity_skill_configs",
            loader: (origin: Record<string, string>[]) => {
                const rst = new Map<string, PeculiaritySkillConfigs>();

                for (const oo of origin) {
                    try {
                        const peculiarityId = Long.fromString(oo["peculiarity_id"]);
                        const stage = parseInt(oo["stage"], 10);
                        const requiredLevel = parseInt(oo["required_level"], 10);
                        const skillId = Long.fromString(oo["skill_id"]);
                        const uk = `${oo["peculiarity_id"]}-${oo["stage"]}`;
                        const config: PeculiaritySkillConfigs = {
                            peculiarityId,
                            stage,
                            requiredLevel,
                            skillId
                        };

                        rst.set(uk, config);
                    } catch (error) {
                        console.error(`解析peculiarity_skill_configs行数据失败:`, oo, error);
                    }
                }

                return rst;
            }
        },
        {
            name: "mixing_formula_configs",
            loader: (origin: Record<string, string>[]) => {
                const rst = new Map<string, MixingFormulaConfigs>();

                for (const oo of origin) {
                    try {
                        const id = Long.fromString(oo["id"]);
                        const sr = this.simpleRateFromRaw(oo['success_rate'])
                        let ssr: SimpleRate | undefined = undefined
                        if (sr.length > 0) {
                            ssr = sr[0]
                        }
                        const config: MixingFormulaConfigs = {
                            id: id,
                            name: oo["name"],
                            desc: oo["desc"],
                            input: this.simpleRewardsFromRaw(oo['input']),
                            showInput: this.simpleRewardsFromRaw(oo['show_input']),
                            successOutput: this.simpleRewardsFromRaw(oo['success_output']),
                            successShowOutput: this.simpleRewardsFromRaw(oo['success_show_output']),
                            failedOutput: this.simpleRewardsFromRaw(oo['failed_show_output']),
                            failedShowOutput: this.simpleRewardsFromRaw(oo['failed_show_output']),
                            successRate: ssr,
                            costMs: Long.fromString(oo['cost_ms']),
                            tag: oo['tag']
                        };

                        rst.set(oo["id"], config);
                    } catch (error) {
                        console.error(`解析mixing_formula_configs行数据失败:`, oo, error);
                    }
                }

                return rst;
            }
        },
        {
            name: "mix_pipe_configs",
            loader: (origin: Record<string, string>[]) => {
                const rst = new Map<string, MixPipeConfigs>();
                for (const oo of origin) {
                    try {
                        rst.set(oo['pipe_tag'] + oo['level'], MixPipeConfigs.create(
                            {
                                pipeTag: oo['pipe_tag'],
                                level: parseInt(oo['level']),
                                formulaId: Long.fromString(oo['formula_id']),
                                maxProduce: parseInt(oo['max_produce']),
                            }
                        ));
                    } catch (error) {
                        console.error(`解析mix_pipe_configs行数据失败:`, oo, error);
                    }
                }
                return rst;
            }
        },
        {
            name: "buildings_configs",
            loader: (origin: Record<string, string>[]) => {
                const rst = new Map<string, BuildingConfigs>();
                for (const oo of origin) {
                    try {
                        const config: BuildingConfigs = {
                            buildingId: Long.fromString(oo['id']),
                            propId: Long.fromString(oo['prop_id']),
                            buildingType: parseInt(oo['building_type']),
                            removeMs: Long.fromString(oo['remove_ms']),
                            height: parseInt(oo['height']),
                            width: parseInt(oo['width']),
                            removable: parseInt(oo['removable']) == 1,
                            movable: parseInt(oo['movable']) == 1,
                            removeRewards: this.simpleRewardsFromRaw(oo['remove_rewards']),
                            canBuild: parseInt(oo['can_build']) == 1,
                        };
                        rst.set(oo['id'], config);
                    } catch (error) {
                        console.error(`解析buildings_configs行数据失败:`, oo, error);
                    }
                }
                return rst;
            }
        },
        {
            name: "building_upgrade_configs",
            loader: (origin: Record<string, string>[]) => {
                const rst = new Map<string, BuildingUpgradeConfigs>();
                for (const oo of origin) {
                    try {
                        const config: BuildingUpgradeConfigs = {
                            buildingId: Long.fromString(oo['building_id']),
                            level: parseInt(oo['level']),
                            requiredRewards: this.simpleRewardsFromRaw(oo['required_rewards']),
                            rewards: this.simpleRewardsFromRaw(oo['rewards']),
                            costMs: Long.fromString(oo['cost_ms']),
                            fishNumLimit: parseInt(oo['fish_limit']),
                        };
                        const uk = oo['building_id'] + '-' + oo['level']
                        rst.set(uk, config);
                    } catch (error) {
                        console.error(`解析building_upgrade_configs行数据失败:`, oo, error);
                    }
                }
                return rst;
            }
        },
        {
            name: "player_level_configs",
            loader: (origin: Record<string, string>[]) => {
                const rst = new Map<string, PlayerLevelConfigs>();

                for (const oo of origin) {
                    try {
                        const level = parseInt(oo["level"]);
                        const requireExp = Long.fromString(oo['require_exp']);
                        const workerNum = parseInt(oo["worker_num"]);
                        const config: PlayerLevelConfigs = {
                            level: level,
                            levelName: oo['level_name'],
                            requireExp: requireExp,
                            buildingLevelLimit: this.longNumberMap(oo['building_level_limit']),
                            buildingNumLimit: this.longNumberMap(oo['building_num_limit']),
                            workerNum: workerNum,
                        };

                        rst.set(oo["level"], config);
                    } catch (error) {
                        console.error(`解析player_level_configs行数据失败:`, oo, error);
                    }
                }

                return rst;
            }
        },
        {
            name: "zone_configs",
            loader: (origin: Record<string, string>[]) => {
                const rst = new Map<string, ZoneConfigs>();
                for (const oo of origin) {
                    try {
                        const config: ZoneConfigs = {
                            zoneId: parseInt(oo['zone_id']),
                            zoneName: oo['zone_name'],
                            zoneIcon: oo['zone_icon'],
                            wildNumLimit: parseInt(oo['wild_num_limit']),
                            wildLevelStart: parseInt(oo['wild_level_start']),
                            wildLevelEnd: parseInt(oo['wild_level_end']),
                            outputRewards: this.simpleRewardsFromRaw(oo['output_rewards']),
                        };
                        rst.set(oo["zone_id"], config);
                    } catch (error) {
                        console.error(`解析zone_configs行数据失败:`, oo, error);
                    }
                }
                return rst;
            }
        },
        {
            name: "asset_props_configs",
            loader: (origin: Record<string, string>[]) => {
                return this.readPropConfigs(origin);
            }
        },
        {
            name: "attrs_props_configs",
            loader: (origin: Record<string, string>[]) => {
                return this.readPropConfigs(origin);
            }
        },
        {
            name: "materials_props_configs",
            loader: (origin: Record<string, string>[]) => {
                return this.readPropConfigs(origin);
            }
        },
        {
            name: "buildings_props_configs",
            loader: (origin: Record<string, string>[]) => {
                return this.readPropConfigs(origin);
            }
        },
    ];

    private readPropConfigs(origin: Record<string, string>[]) {
        const rst = new Map<string, PropsConfigs>();
        for (const oo of origin) {
            try {
                const propId = Long.fromString(oo["id"]);
                const quality = parseInt(oo["quality"], 10);
                const config: PropsConfigs = {
                    id: propId,
                    name: oo["name"] || "",
                    desc: oo["desc"] || "",
                    quality: quality,
                    icon: oo["icon"] || "",
                    showInBag: this.numberList(oo["show_in_bag"]),
                    way: this.numberList(oo["way"]),
                };

                rst.set(oo["id"], config);
            } catch (error) {
                console.error(`解析props行数据失败:`, oo, error);
            }
        }

        return rst;
    }

    /**
     * 辅助函数：将字符串转换为KV列表
     */
    private tuple2List(raw: string): KVHelper[] {
        const rst: KVHelper[] = [];
        if (!raw) return rst;

        const pairs = raw.split(';');
        for (const pair of pairs) {
            const tp = pair.split(':');
            if (tp.length === 2) {
                rst.push({
                    k: tp[0].trim(),
                    v: tp[1].trim()
                });
            }
        }
        return rst;
    }

    /**
     * 辅助函数：将字符串转换为number list
     */
    private numberList(raw: string): number[] {
        const rst: number[] = [];
        if (!raw) return rst;
        const pairs = raw.split(';');
        for (const pair of pairs) {
            rst.push(parseInt(pair, 10))
        }
        return rst;
    }

    /**
     * 辅助函数：将字符串转换为number list
     */
    private longNumberMap(raw: string): Map<Long, number> {
        return cmm.array2Map(this.tuple2List(raw), (item) => {
            return {
                k: Long.fromString(item.k),
                v: parseInt(item.v),
            };
        });
    }

    /**
     * 辅助函数：从原始字符串解析简单属性
     */
    private simpleAttrsFromRaw(raw: string): SimpleAttrs[] {
        return this.tuple2List(raw)
            .map(item => {
                const attrType = parseInt(item.k, 10);
                const attr = parseInt(item.v, 10);
                if (isNaN(attrType) || isNaN(attr)) {
                    return null;
                }
                return SimpleAttrs.create({attrType, attr});
            })
            .filter(item => item !== null) as SimpleAttrs[];
    }

    /**
     * 辅助函数：从原始字符串解析简单概率
     */
    private simpleRateFromRaw(raw: string): SimpleRate[] {
        return this.tuple2List(raw)
            .map(item => {
                const id = parseInt(item.k, 10);
                const rate = parseInt(item.v, 10);
                if (isNaN(id) || isNaN(rate)) {
                    return null;
                }
                return SimpleRate.create({id, rate});
            })
            .filter(item => item !== null) as SimpleRate[];
    }

    /**
     * 辅助函数：从原始字符串解析简单概率
     */
    private simpleRewardsFromRaw(raw: string): SimpleRewards[] {
        return this.tuple2List(raw)
            .map(item => {
                const propId = parseInt(item.k, 10);
                const num = parseInt(item.v, 10);
                if (isNaN(propId) || isNaN(num)) {
                    return null;
                }
                return SimpleRewards.create({propId, num});
            })
            .filter(item => item !== null) as SimpleRewards[];
    }

    start() {
        this.init()
        GlobalConfigsLoader.instance = this
    }

    init() {
        this.originConfigs = cmm.array2Map(this.configHelpers, (helper) => {
            const origin = CSVReader.readCSVToArray(helper.name)
            console.log('try load config:', helper.name)
            return {
                k: helper.name,
                v: helper.loader(origin)
            }
        })
        this.originConfigs.forEach((configs, name) => {
            console.log('global configs loaded: name ', name);
            configs.forEach((config, uk) => console.log('config:', uk, '=>', config));
        })

    }

    public getFishLevelConfigs(): Map<string, FishLevelConfigs> {
        return this.originConfigs.get("fish_level_configs") as Map<string, FishLevelConfigs>;
    }

    public getExtraAttrsConfigs(): Map<string, ExtraAttrsConfigs> {
        return this.originConfigs.get("extra_attrs_configs") as Map<string, ExtraAttrsConfigs>;
    }

    public getTalentConfigs(): Map<string, TalentConfigs> {
        return this.originConfigs.get("talent_configs") as Map<string, TalentConfigs>;
    }

    public getFishLooksConfigs(): Map<string, FishLooksConfigs> {
        return this.originConfigs.get("fish_looks_configs") as Map<string, FishLooksConfigs>;
    }

    public getPersonalityConfigs(): Map<string, PersonalityConfigs> {
        return this.originConfigs.get("personality_configs") as Map<string, PersonalityConfigs>;
    }

    public getPeculiarityConfigs(): Map<string, PeculiarityConfigs> {
        return this.originConfigs.get("peculiarity_configs") as Map<string, PeculiarityConfigs>;
    }

    public getPeculiaritySkillConfigs(): Map<string, PeculiaritySkillConfigs> {
        return this.originConfigs.get("peculiarity_skill_configs") as Map<string, PeculiaritySkillConfigs>;
    }

    public getLingGenConfigs(): Map<string, LingGenConfigs> {
        return this.originConfigs.get("ling_gen_configs") as Map<string, LingGenConfigs>;
    }

    public getSkillsConfigs(): Map<string, SkillConfigs> {
        return this.originConfigs.get("skills_configs") as Map<string, SkillConfigs>;
    }

    public getMixingFormulaConfigs(): Map<string, MixingFormulaConfigs> {
        return this.originConfigs.get("mixing_formula_configs") as Map<string, MixingFormulaConfigs>;
    }

    public getMixPipeConfigs(): Map<string, MixPipeConfigs> {
        return this.originConfigs.get("mix_pipe_configs") as Map<string, MixPipeConfigs>;
    }

    public getBuildingConfigs(): Map<string, BuildingConfigs> {
        return this.originConfigs.get("buildings_configs") as Map<string, BuildingConfigs>;
    }


    public getBuildingUpgradeConfigs(): Map<string, BuildingUpgradeConfigs> {
        return this.originConfigs.get("building_upgrade_configs") as Map<string, BuildingUpgradeConfigs>;
    }

    public getPlayerLevelConfigs(): Map<string, PlayerLevelConfigs> {
        return this.originConfigs.get("player_level_configs") as Map<string, PlayerLevelConfigs>;
    }

    public getZoneConfigs(): Map<string, ZoneConfigs> {
        return this.originConfigs.get("zone_configs") as Map<string, ZoneConfigs>;
    }


    public getPropsConfigs(): Map<string, PropsConfigs> {
        const assetProps = this.originConfigs.get("asset_props_configs") as Map<string, PropsConfigs>;
        const attrsProps = this.originConfigs.get("attrs_props_configs") as Map<string, PropsConfigs>;
        const materialsProps = this.originConfigs.get("materials_props_configs") as Map<string, PropsConfigs>;
        const buildingsProps = this.originConfigs.get("buildings_props_configs") as Map<string, PropsConfigs>;
        const props = new Map<string, PropsConfigs>();
        assetProps.forEach((asset, key) => props.set(key, asset));
        attrsProps.forEach((asset, key) => props.set(key, asset));
        materialsProps.forEach((asset, key) => props.set(key, asset));
        buildingsProps.forEach((asset, key) => props.set(key, asset));
        // return new Map<string, PropsConfigs>([...assetProps, ...attrsProps, ...materialsProps, ...buildingsProps])
        return props;
    }

}

